package net.wanderinghorse.jsonmessage;

import net.wanderinghorse.json.JSONArray;
import net.wanderinghorse.json.JSONObject;

/**
 * An abstract base type for RequestHandler objects which sets certain
 * common properties on the responses they handle.
 */
public abstract class AbstractRequestHandler implements RequestHandler {
    /**
     * The default response resultCode used by this class' internal error handling.
     */
    public static final int DEFAULT_ERROR_RC = 1;
    /**
     * Must be overridden by subclasses and behave as described for
     * ResponseHandler.processResponse().
     * 
     * @param req The request object which caused the fetching of the response.
     * @param resp The response object to populate.
     * @throws Exception Implementations may throw arbitrary exceptions. This class' post()
     * impl will wrap up the error information inside the resp object. 
     * */
    abstract protected void doProcessResponse(Request req, Response resp)  throws Exception;

    /**
     * A convenience method to set resp's resultCode and resultText, and
     * clears its payload.
     *
     * @param resp The response to modify.
     * @param rc The error code. If it is 0 then DEFAULT_ERROR_RC is used.
     * @param ex The exception to pull the message string from.
     */
    protected void setErrorState( Response resp, int rc, Exception ex ) {
        resp.setResultCode( (0==rc) ? DEFAULT_ERROR_RC : rc );
        resp.setResultText( ex.toString() );
        resp.setPayload( null );
    }
    /**
     * Sets up resp's "responseTo" and "type" properties to the id resp.
     * type of req, then calls the protected doProcessResponse() to do
     * any type-specific handling. If doProcessResponse() throws then
     * resp's payload is removed and resp is populated with information
     * for reporting the error.
     *
     * @param req The request object which caused the fetching of the response.
     * @param resp The response object to populate.
     */
    public final void processResponse(final Request req, final Response resp) throws Exception {
        resp.setRequestId( req.getId() );
        resp.setType( req.getType() );
        try {
            this.doProcessResponse(req, resp);
        }
        catch( Exception ex ) {
            setErrorState( resp, DEFAULT_ERROR_RC, ex );
        }
    }

    /**
     * Convenience method to extract a JSONObject payload. 
     *
     * @param r The request object.
     * @return If r.getPayload() is-a JSONObject, that object is returned,
     * else null is returned.
     */
    protected JSONObject getPayloadObject( Request r ) {
        Object inpay = r.getPayload();
        return ( inpay instanceof JSONObject )
                ? (JSONObject)inpay
                : null;
    }

    /**
     * Convenience method to extract a JSONArray payload.
     *
     * @param r The request object.
     * @return If r.getPayload() is-a JSONArray, that object is returned,
     * else null is returned.
     */
    protected JSONArray getPayloadArray( Request r ) {
        Object inpay = r.getPayload();
        return ( inpay instanceof JSONArray )
                ? (JSONArray)inpay
                : null;
    }

}
